﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace Pavilion.DesignerTool
{
    public class GameDataWrapper : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public event Action<GameDataWrapper, string> PropertyAdded, PropertyRemoved;

        public GameData GameData { get; private set; }
        public bool IsLoadItem { get; set; }
        public NotifiableCollection<string> PropertiesCollection { get; private set; }
        public NotifiableCollection<string> CompleteListOfProperties { get; private set; }
        public NodeBaseWrapper NodeWrapperParent { get; private set; }

        public IEnumerable<GameItemWrapper> GameItemCollection { get { return GameItemWrapperManager.GameItemWrapperCollection; } }
        public string SelectedGameItemDisplayName { get { return "GameItem: " + GameItemWrapperManager.GetGameItemWrapper(GameData.GameItemName).Name; } }

        public GameDataWrapper(GameData gameData, NodeBaseWrapper nodeWrapperParent)
        {
            this.GameData = gameData;
            this.NodeWrapperParent = nodeWrapperParent;

            PropertiesCollection = new NotifiableCollection<string>(gameData.PropertyDictionary.Keys);

            Type gameToolType = GetGameToolType(GameData);
            CompleteListOfProperties = new NotifiableCollection<string>(gameToolType.GetProperties().Where(x => x.CanWrite).Select<System.Reflection.PropertyInfo, string>(p => p.Name));

            foreach (string propertyName in gameData.PropertyDictionary.Keys)
                CompleteListOfProperties.Remove(propertyName);
        }

        static public Type GetGameToolType(GameData gameData)
        {
            return GameEngine.GetType("Pavilion.GameTools.dll", gameData.GameToolName);
        }

        public void AddProperty(string propertyName)
        {
            CompleteListOfProperties.Remove(propertyName);

            GameData.AddData(propertyName, GetDefaultValue(propertyName));
            PropertiesCollection.Add(propertyName);

            if (IsLoadItem)
                GameToolTransfer.AddGameToolProperty(this, propertyName);
            else
                GameDataTransfer.AddProperty(this, propertyName, GetPropertyValue(propertyName));

            OnPropertyAdded(propertyName);
        } 

        public void RemoveProperty(string propertyName)
        {
            CompleteListOfProperties.Add(propertyName);
            GameData.RemoveData(propertyName);
            PropertiesCollection.Remove(propertyName);

            if (IsLoadItem)
                GameToolTransfer.RemoveGameToolProperty(this, propertyName);
            else
                GameDataTransfer.RemoveProperty(this, propertyName);

            OnPropertyRemoved(propertyName);
        }

        private object GetDefaultValue(string propertyName)
        {
            Type gameToolType = GetGameToolType(GameData);

            foreach (System.Reflection.PropertyInfo property in gameToolType.GetProperties())
            {
                if (property.Name == propertyName)
                    return GameEngine.CreateInstance(property.PropertyType);
            }

            return null;
        }

        public object GetPropertyValue(string propertyName)
        {
            if (propertyName == "GameItemName")
                return GameData.GameItemName;
            else
                return GameData.PropertyDictionary[propertyName];
        }

        public void SetPropertyValue(string propertyName, object value)
        {
            if (propertyName == "GameItemName")
                SetGameItemName(value.ToString());
            else
            {
                GameData.PropertyDictionary[propertyName] = value;

                if (IsLoadItem)
                    GameToolTransfer.UpdateGameToolProperty(this, propertyName);
                else
                    GameDataTransfer.Update(this, propertyName, value);
            }
        }

        public void SetGameItemName(string gameItemName)
        {
            GameData.GameItemName = gameItemName;
            GameDataTransfer.UpdateGameItemName(this);

            OnPropertyChanged("SelectedGameItemDisplayName");
        }

        public override string ToString()
        {
            return GameData.GameToolName;
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnPropertyAdded(string propertyName)
        {
            if (PropertyAdded != null)
                PropertyAdded(this, propertyName);
        }

        private void OnPropertyRemoved(string propertyName)
        {
            if (PropertyRemoved != null)
                PropertyRemoved(this, propertyName);
        }
    }
}
